/*
 * game.c
 *
 *  Created on: 15 nov. 2010
 *      Author: Nicolas Aucouturier, Laurent R�veill�re
 */

#include <assert.h>
#include <time.h>

#include "../include/game.h"
#include "../include/map.h"
#include "../include/player.h"
#include "../include/misc.h"
#include "../include/level.h"
#include "../include/player.h"
#include "../include/bomb.h"
#include "../include/bomb_list.h"
#include "../include/monster.h"
#include "../include/monster_list.h"

struct s_game {
	t_level curr_level; // current level
	t_player player;
	t_bomb_list bomb_list;
	t_monster_list monster_list;

	SDL_Surface * number[10];
	SDL_Surface * banner_life;
	SDL_Surface * banner_bomb;
	SDL_Surface * banner_range;
	SDL_Surface * banner_line;
	SDL_Surface * banner_key;
	SDL_Surface * banner_flag;
	SDL_Surface * banner_level;
};

static struct s_game the_game;

t_game game_new(void) {
	srand(time(NULL));

	the_game.curr_level = level_get_level(0); // get maps of the first level

	the_game.monster_list = monster_list_init(monster_init());//initialize our monster list
	the_game.player = player_init(3, 2, 3);//initialize the player
	//initialize our bomb list
	the_game.bomb_list = bomb_list_init(
			set_bomb(player_get_x(the_game.player),
					player_get_y(the_game.player), the_game.player));
	player_from_map(the_game.player, level_get_map(the_game.curr_level, 0)); // get x,y of the player on the first map
	monster_list_from_map(the_game.monster_list,
			level_get_map(the_game.curr_level, 0));// get x,y of the monster on the first map
	/* load banner's imgs in memory */
	the_game.number[0] = load_image(IMG_BANNER_0);
	the_game.number[1] = load_image(IMG_BANNER_1);
	the_game.number[2] = load_image(IMG_BANNER_2);
	the_game.number[3] = load_image(IMG_BANNER_3);
	the_game.number[4] = load_image(IMG_BANNER_4);
	the_game.number[5] = load_image(IMG_BANNER_5);
	the_game.number[6] = load_image(IMG_BANNER_6);
	the_game.number[7] = load_image(IMG_BANNER_7);
	the_game.number[8] = load_image(IMG_BANNER_8);
	the_game.number[9] = load_image(IMG_BANNER_9);
	the_game.banner_life = load_image(IMG_BANNER_LIFE);
	the_game.banner_bomb = load_image(IMG_BANNER_BOMB);
	the_game.banner_range = load_image(IMG_BANNER_RANGE);
	the_game.banner_line = load_image(IMG_BANNER_LINE);
	the_game.banner_key = load_image(IMG_MAP_KEY);
	the_game.banner_flag = load_image(IMG_MAP_GOAL);
	the_game.banner_level = load_image(IMG_BANNER_LEVEL);
	return &the_game;
}

void game_free(t_game game) {
	assert(game);
	player_free(game->player);
	level_free(game->curr_level);
}

t_player game_get_player(t_game game) {
	assert(game);
	return game->player;
}


t_bomb_list game_get_bomb_list(t_game game) {
	assert(game);
	return game->bomb_list;
}

t_monster_list game_get_monster_list(t_game game) {
	assert(game);
	return game->monster_list;
}
void game_banner_display(t_game game, SDL_Surface* screen) {
	assert(game);
	assert(screen);

	t_map map = level_get_curr_map(game_get_curr_level(game));

	SDL_Rect place;

	int i;
	place.y = (map_get_height(map)) * SIZE_BLOC;
	for (i = 0; i < map_get_width(map); i++) {
		place.x = i * SIZE_BLOC;
		SDL_BlitSurface(game->banner_line, NULL, screen, &place);
	}

	place.y = (map_get_height(map) * SIZE_BLOC) + SIZE_LINE;

	int white_bloc = ((map_get_width(map) * SIZE_BLOC) - 6 * SIZE_BLOC) / 4;

	place.x = white_bloc;
	SDL_BlitSurface(game->banner_life, NULL, screen, &place);
	place.x = white_bloc + SIZE_BLOC;
	SDL_BlitSurface(game->number[player_get_nb_life(game_get_player(game))],
			NULL, screen, &place);//link player's life and banner

	place.x = 1 * white_bloc + 2 * SIZE_BLOC;
	SDL_BlitSurface(game->banner_bomb, NULL, screen, &place);
	place.x = 1 * white_bloc + 3 * SIZE_BLOC;
	;
	if (player_get_nb_bomb(game_get_player(game)) >= 0 && player_get_nb_bomb(
			game_get_player(game)) < 10)
		SDL_BlitSurface(
				game->number[player_get_nb_bomb(game_get_player(game))], NULL,
				screen, &place);//link number of bomb of the player and the banner

	place.x = 1 * white_bloc + 4 * SIZE_BLOC;
	SDL_BlitSurface(game->banner_range, NULL, screen, &place);
	place.x = 1 * white_bloc + 5 * SIZE_BLOC;
	int bomb_range = player_get_bomb_range(game->player);
	SDL_BlitSurface(game->number[bomb_range], NULL, screen, &place);//link bomb power and banner

	//link level and banner
	place.x = 1 * white_bloc + 6 * SIZE_BLOC;
	SDL_BlitSurface(game->banner_level, NULL, screen, &place);
	place.x = 1 * white_bloc + 7 * SIZE_BLOC;
	int level = level_get_level_nb(game->curr_level) + 1;
	SDL_BlitSurface(game->number[level], NULL, screen, &place);

	if (player_has_key(game->player)) {
		place.x = 1 * white_bloc + 8 * SIZE_BLOC;
		SDL_BlitSurface(game->banner_key, NULL, screen, &place);//add key on the map when the player has it
	}
}

void game_display(t_game game, SDL_Surface* screen) {
	assert(game);
	t_map map = level_get_curr_map(game_get_curr_level(game));
	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));

	game_banner_display(game, screen);
	map_display(map, screen);
	level_display(game_get_curr_level(game), screen);
	player_display(game->player, screen);
	player_gameover_display(screen, game->player);
	player_victory_display(screen, game->player);
	bomb_list_display(game->bomb_list, map, game->player, game->monster_list,
			screen);
	monster_list_display(game->monster_list, map, game->player, screen);
	SDL_Flip(screen); // SDL_Flip -- swaps screen buffers -- update
}

t_level game_get_curr_level(t_game game) {
	return game->curr_level;
}

int input_update(t_game game, SDL_Surface *screen) {
	SDL_Event event;
	t_player player = game_get_player(game);
	t_monster_list monster_list = game_get_monster_list(game);
	t_map map = level_get_curr_map(game_get_curr_level(game));
	bomb_list_update(game->bomb_list);//the bomb list is update
	monster_list_update(game->monster_list);//the monster list is update
	while (SDL_PollEvent(&event)) {
		switch (event.type) {
		case SDL_QUIT:
			return 1;
		case SDL_KEYDOWN:
			switch (event.key.keysym.sym) {
			case SDLK_ESCAPE:
				return 1;
			case SDLK_UP:
				player_set_current_way(player, NORTH);
				player_move(player, map, screen);
				game_change_map(game);
				break;
			case SDLK_DOWN:
				player_set_current_way(player, SOUTH);
				player_move(player, map, screen);
				game_change_map(game);
				break;
			case SDLK_RIGHT:
				player_set_current_way(player, EAST);
				player_move(player, map, screen);
				game_change_map(game);
				break;
			case SDLK_LEFT:
				player_set_current_way(player, WEST);
				player_move(player, map, screen);
				game_change_map(game);
				break;
			case SDLK_SPACE:
				if (player_get_nb_bomb(player) > 0) {//a bomb is create and put inside the bomb list as long as the player is able to set a bom
					list_add(
							the_game.bomb_list,
							set_bomb(player_get_x(player),
									player_get_y(player), the_game.player));
					player_dec_nb_bomb(player);
				}
				break;
			default:
				break;
			}

			break;
		}
	}
	return 0;
}

int game_update(t_game game, SDL_Surface *screen) {
	if (input_update(game, screen) == 1) {
		return 1;
	}

	return 0;
}

int game_change_map(t_game game, SDL_Surface *screen) {
	assert(game);

	int x = 0;

	if (player_has_reached_gate(game->player)) {//player has reached the gate so we have to change the map
		if (level_get_cur_map(game->curr_level) < level_get_nb_maps(
				game->curr_level)) {
			level_inc_cur_map(game->curr_level);
			player_dec_reached_gate(game->player);
			x = 1;//caracterize what we are going to do
		}
	}
	if (player_has_goal(game->player) == 1) {//player has reached the goal so we have to change level
		if (level_get_level_nb(game->curr_level) < 1) {
			//map_free(level_get_cur_map(game->curr_level));
			game->curr_level = level_get_level(
					level_inc_level_nb(game->curr_level));
			player_dec_has_goal(game->player);
			x = 2;
		}//caracterize what we are going to do
	}

	if (x == 1) {//the gate has been reached
		player_from_map(game->player,
				level_get_curr_map(game_get_curr_level(game)));//decide where the player will appear on the new map
		the_game.monster_list = monster_list_init(monster_init());//we will have new monster
		monster_list_from_map(game->monster_list,
				level_get_curr_map(game_get_curr_level(game)));
		the_game.bomb_list = bomb_list_init(
				set_bomb(player_get_x(the_game.player),
						player_get_y(the_game.player), the_game.player));//prevent the effect of the bomb on previous map
	} else if (x == 2) {//the goal has been reached
		the_game.player = player_init(9, 9, 3);
		player_from_map(game->player,
				level_get_curr_map(game_get_curr_level(game)));
		the_game.monster_list = monster_list_init(monster_init());
		monster_list_from_map(game->monster_list,
				level_get_curr_map(game_get_curr_level(game)));
		the_game.bomb_list = bomb_list_init(
				set_bomb(player_get_x(the_game.player),
						player_get_y(the_game.player), the_game.player));
	}
}

